using System.Collections.Generic;
using System.Data;
using Comdiv.Application;
using Comdiv.Conversations;
using Comdiv.Inversion;
using Comdiv.IO;
using Comdiv.Logging;
using Comdiv.Model;
using Comdiv.Model.Interfaces;
using Comdiv.Persistence;
using Comdiv.Security;
using Comdiv.Security.Acl;

namespace Comdiv.Messaging{
    /// <summary>
    /// abstract message query executor that is thread safe and prepares usefull services from container
    /// </summary>
    public abstract class MessageQueryExecutorBase : IMessageQueryExecutor{
        private IInversionContainer _container;
        private StorageWrapper<IMessage> _storage;

        public IInversionContainer Container{
            get{
                if (_container.invalid()){
                    lock (this){
                        if (_container.invalid()){
                            Container = ioc.Container;
                        }
                    }
                }
                return _container;
            }
            set { _container = value; }
        }

        public StorageWrapper<IMessage> Storage{
            get{
                lock (this){
                    if (null == _storage){
                        _storage = myapp.storage.Get<IMessage>();
                    }
                    return _storage;
                }
            }
            set { lock (this) _storage = value; }
        }

        #region IMessageQueryExecutor Members

        public IEnumerable<IMessage> Query(IMessageQuery query){
            lock (this){
                return doQuery(query);
            }
        }

        public void MarkRead(IMessage message, string usr, bool readed){
            lock (this){
                doMarkRead(message, usr, readed);
            }
        }

        public void MarkArchive(IMessage message, string usr, bool archived){
            lock (this){
                doMarkArchive(message, usr, archived);
            }
        }

        public bool IsReaded(IMessage message, string usr){
            lock (this){
                return doIsReaded(message, usr);
            }
        }

        public bool IsArchived(IMessage message, string usr){
            lock (this){
                return doIsArchived(message, usr);
            }
        }

        #endregion

        protected IDbConnection GetConnection(){
            lock (this){
                return Container.getConnection();
            }
        }


        public abstract IEnumerable<IMessage> doQuery(IMessageQuery query);
        public abstract void doMarkRead(IMessage message, string usr, bool readed);
        public abstract void doMarkArchive(IMessage message, string usr, bool archived);
        public abstract bool doIsReaded(IMessage message, string usr);
        public abstract bool doIsArchived(IMessage message, string usr);
    }
}